#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <jsoncpp/json/json.h>
#include <mysql/mysql.h>
#include <cstdio>
#include <fstream>

namespace as_model
{
    class model
    {
    public:
        model()
        {
        }
        ~model()
        {
        }

    public:
        int execute_query(MYSQL *conn, const char *_username, const char *_password)
        {
            char query[256];
            snprintf(query, sizeof(query), "select * from user where username='%s' and password='%s'", _username, _password);
            // 执行 SQL 查询
            if (mysql_query(conn, query))
            {
                fprintf(stderr, "查询执行失败: %s\n", mysql_error(conn));
                return 0;
            }
            // 获取查询结果集
            MYSQL_RES *result = mysql_store_result(conn);
            if (result == NULL)
            {
                fprintf(stderr, "获取结果集失败: %s\n", mysql_error(conn));
                return 0;
            }
            // 获取结果集中的行数
            int num_rows = mysql_num_rows(result);
            // 释放结果集
            mysql_free_result(result);
            // 根据行数判断是否有查询结果
            if (num_rows > 0)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        int search_mysql(const std::string in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_username = in_value["username"].asString();
            std::string information_password = in_value["password"].asString();

            // 初始化 MySQL 连接
            MYSQL *conn = mysql_init(NULL);
            if (conn == NULL)
            {
                fprintf(stderr, "MySQL 初始化失败: %s\n", mysql_error(conn));
                return 1;
            }
            // 连接到 MySQL 数据库
            if (mysql_real_connect(conn, "localhost", "root", "", "as_db", 0, NULL, 0) == NULL)
            {
                fprintf(stderr, "连接数据库失败: %s\n", mysql_error(conn));
                mysql_close(conn);
                return 1;
            }
            // 执行查询并获取结果
            const char *elem_1 = information_username.c_str();
            const char *elem_2 = information_password.c_str();
            int result = execute_query(conn, elem_1, elem_2);
            // 关闭 MySQL 连接
            mysql_close(conn);

            return result;
        }

    public:
        int execute_insert(MYSQL *conn, const char *_emotion, const char *_content)
        {
            if (!_emotion || !_content) {
                fprintf(stderr, "无效的输入参数\n");
                return -1;
            }

            char *esc_emotion = (char *)malloc(strlen(_emotion) * 2 + 1);
            char *esc_content = (char *)malloc(strlen(_content) * 2 + 1);
            if (!esc_emotion || !esc_content) {
                fprintf(stderr, "内存分配失败\n");
                free(esc_emotion);
                free(esc_content);
                return -1;
            }
                
            mysql_real_escape_string(conn, esc_emotion, _emotion, strlen(_emotion));
            mysql_real_escape_string(conn, esc_content, _content, strlen(_content));

            char check_sql[512];  // 增加缓冲区大小
            int needed = snprintf(check_sql, sizeof(check_sql), "SELECT label FROM corpus WHERE label = '%s'",esc_emotion);
                
            if (needed >= sizeof(check_sql)) {
                fprintf(stderr, "查询语句过长\n");
                free(esc_emotion);
                free(esc_content);
                return -1;
            }
                
            if (mysql_query(conn, check_sql)) {
                fprintf(stderr, "查询失败: %s\n", mysql_error(conn));
                free(esc_emotion);
                free(esc_content);
                return -1;
            }

            MYSQL_RES *res = mysql_store_result(conn);
            int exists = 0;
            if (res) {
                exists = (mysql_num_rows(res) > 0);
                mysql_free_result(res);
            }

            int result = -1;
            if (exists) {
                char *update_sql = (char *)malloc(200 + strlen(esc_emotion) + strlen(esc_content) * 2);
                if (!update_sql) {
                    fprintf(stderr, "内存分配失败\n");
                    free(esc_emotion);
                    free(esc_content);
                    return -1;
                }
                        
                snprintf(update_sql, 200 + strlen(esc_emotion) + strlen(esc_content) * 2,
                        "UPDATE corpus SET content = CONCAT(content, '\\n', '%s') ""WHERE label = '%s'",esc_content, esc_emotion);
                        
                if (mysql_query(conn, update_sql)) {
                    fprintf(stderr, "更新失败: %s\n", mysql_error(conn));
                } else {
                    result = 1; // 更新成功
                }
                free(update_sql);
            } else {
                char *insert_sql = (char *)malloc(100 + strlen(esc_emotion) + strlen(esc_content));
                if (!insert_sql) {
                    fprintf(stderr, "内存分配失败\n");
                    free(esc_emotion);
                    free(esc_content);
                    return -1;
                }
                        
                snprintf(insert_sql, 100 + strlen(esc_emotion) + strlen(esc_content),
                        "INSERT INTO corpus (label, content) VALUES ('%s', '%s')",esc_emotion, esc_content);
                        
                if (mysql_query(conn, insert_sql)) {
                    fprintf(stderr, "插入失败: %s\n", mysql_error(conn));
                } else {
                    result = 1; // 插入成功
                }
                free(insert_sql);
            }

            free(esc_emotion);
            free(esc_content);
            return result;
        }
        int import_mysql(const std::string in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_emotion = in_value["emotion"].asString();
            std::string information_content = in_value["content"].asString();

            // 初始化 MySQL 连接
            MYSQL *conn = mysql_init(NULL);
            if (conn == NULL)
            {
                fprintf(stderr, "MySQL 初始化失败: %s\n", mysql_error(conn));
                return 1;
            }
            // 连接到 MySQL 数据库
            if (mysql_real_connect(conn, "localhost", "root", "", "as_db", 0, NULL, 0) == NULL)
            {
                fprintf(stderr, "连接数据库失败: %s\n", mysql_error(conn));
                mysql_close(conn);
                return 1;
            }

            // 设置字符集为 utf8mb4
            if (mysql_set_character_set(conn, "utf8mb4") != 0)
            {
                fprintf(stderr, "设置字符集失败: %s\n", mysql_error(conn));
                mysql_close(conn);
                return 1;
            }

            // 执行查询并获取结果
            const char *elem_1 = information_emotion.c_str();
            const char *elem_2 = information_content.c_str();
            int result = execute_insert(conn, elem_1, elem_2);
            // 关闭 MySQL 连接
            mysql_close(conn);

            return result;
        }

    public:
        int execute_modify(MYSQL *conn, const char *_emotion, const char *_content)
        {
            // 构造 SQL 更新语句
            char sql[1024];
            snprintf(sql, sizeof(sql), "update corpus set content = '%s' where label = '%s'", _content, _emotion);

            // 执行 SQL 语句
            if (mysql_query(conn, sql) != 0)
            {
                fprintf(stderr, "执行 SQL 语句出错: %s\n", mysql_error(conn));
                return 0;
            }

            // 获取受影响的行数
            int affected_rows = mysql_affected_rows(conn);
            if (affected_rows > 0)
                return 1;
            else
                return 0;
        }
        int modify_mysql(const std::string in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_emotion = in_value["emotion"].asString();
            std::string information_content = in_value["content"].asString();

            // 初始化 MySQL 连接
            MYSQL *conn = mysql_init(NULL);
            if (conn == NULL)
            {
                fprintf(stderr, "MySQL 初始化失败: %s\n", mysql_error(conn));
                return 1;
            }
            // 连接到 MySQL 数据库
            if (mysql_real_connect(conn, "localhost", "root", "", "as_db", 0, NULL, 0) == NULL)
            {
                fprintf(stderr, "连接数据库失败: %s\n", mysql_error(conn));
                mysql_close(conn);
                return 1;
            }

            // 设置字符集为 utf8mb4
            if (mysql_set_character_set(conn, "utf8mb4") != 0)
            {
                fprintf(stderr, "设置字符集失败: %s\n", mysql_error(conn));
                mysql_close(conn);
                return 1;
            }

            // 执行查询并获取结果
            const char *elem_1 = information_emotion.c_str();
            const char *elem_2 = information_content.c_str();
            int result = execute_modify(conn, elem_1, elem_2);
            // 关闭 MySQL 连接
            mysql_close(conn);

            return result;
        }

    public:
        std::string execute_query(MYSQL *conn, const std::string &_label)
        {
            std::string result;
            // 构建 SQL 查询语句
            std::string query = "select content from corpus where label = '" + _label + "'";

            // 执行 SQL 查询
            if (mysql_query(conn, query.c_str()) != 0)
            {
                std::cerr << "执行查询失败: " << mysql_error(conn) << std::endl;
                return result;
            }

            // 获取查询结果
            MYSQL_RES *res = mysql_store_result(conn);
            if (res == nullptr)
            {
                std::cerr << "获取查询结果失败: " << mysql_error(conn) << std::endl;
                return result;
            }

            // 遍历结果集
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)))
            {
                if (row[0] != nullptr)
                {
                    if (!result.empty())
                    {
                        result += "\n";
                    }
                    result += row[0];
                }
            }

            // 释放结果集
            mysql_free_result(res);

            return result;
        }

        std::string query_mysql(const std::string &in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_label = in_value["label"].asString();

            // 初始化 MySQL 连接
            MYSQL *conn = mysql_init(nullptr);
            if (conn == nullptr)
            {
                std::cerr << "MySQL 初始化失败: " << mysql_error(conn) << std::endl;
                return "";
            }
            // 连接到 MySQL 数据库
            if (mysql_real_connect(conn, "localhost", "root", "", "as_db", 0, nullptr, 0) == nullptr)
            {
                std::cerr << "连接数据库失败: " << mysql_error(conn) << std::endl;
                mysql_close(conn);
                return "";
            }

            // 设置字符集为 utf8mb4
            if (mysql_set_character_set(conn, "utf8mb4") != 0)
            {
                std::cerr << "设置字符集失败: " << mysql_error(conn) << std::endl;
                mysql_close(conn);
                return "";
            }

            // 执行查询并获取结果
            std::string result = execute_query(conn, information_label);

            // 关闭 MySQL 连接
            mysql_close(conn);

            return result;
        }

    public:
        //3.进行json串的反序列化工作，拿到我们要查询的语料关键词
        //4.在这里我们不在去进行数据库的查询工作，这份语料是所有用户所公共的数据，所以我们进行文件操作
        //5.通过文件操作，去查找含有该关键字的语料，将该语料读出并返回拿到，向前传递
        std::string query_modeldatasets(const std::string &in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_keyword = in_value["keyword"].asString();
            std::cout<<"[待查找的模型语料关键字："<<information_keyword<<"]"<<std::endl;
            
            
            std::string filename = "../wwwroot/MainPagehtml/datasets.txt";  // 替换为实际的文件名
            std::string keyword = information_keyword;  // 替换为实际要查找的关键字
            std::ifstream file(filename);
            if (!file.is_open()) {
                std::cerr << "无法打开文件！" << std::endl;
                return "";
            }

            std::string line;
            int line_id = 0;
            std::string found_line;
            bool keyword_found = false;
            while (std::getline(file, line)) {
                line_id++;
                if (line.find(keyword) != std::string::npos) {
                    found_line = line;
                    keyword_found = true;
                    break;
                }
            }
        
            file.close();

            if (keyword_found) {
                std::cout << "[找到关键字为 '" << keyword <<"的语料，"<< "' 在第 " << line_id << " 行:";
                std::cout << found_line<<"]" << std::endl;
            } else {
                std::cout << "[未找到关键字为 '" << keyword << "'的语料。"<<"]" << std::endl;
            }
            
            std::string line_id_str = std::to_string(line_id);
            return line_id_str+"-> "+found_line;
        }


        int replaceLineInFile(const std::string& filename, int lineId, const std::string& content) {
            std::ifstream inputFile(filename);
            if (!inputFile.is_open()) {
                std::cerr << "无法打开文件: " << filename << std::endl;
                return 0;
            }

            std::vector<std::string> lines;
            std::string line;
            // 逐行读取文件内容并存储到向量中
            while (std::getline(inputFile, line)) {
                lines.push_back(line);
            }
            inputFile.close();
            
            // 检查指定的行号是否在有效范围内
            if (lineId < 1 || lineId > static_cast<int>(lines.size())) {
                std::cerr << "指定的行号无效。" << std::endl;
                return 0;
            }
            
            // 替换指定行的内容
            lines[lineId - 1] = content;
            
            std::ofstream outputFile(filename);
            if (!outputFile.is_open()) {
                std::cerr << "无法打开文件进行写入: " << filename << std::endl;
                return 0;
            }
            
            // 将修改后的内容写回文件
            for (size_t i = 0; i < lines.size(); ++i) {
                outputFile << lines[i];
                if (i < lines.size() - 1) {
                    outputFile << '\n';
                }
            }
            outputFile.close();
        
            return 1;
        }
            
    
        int modify_modeldatasets(const std::string &in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_id = in_value["id"].asString();
            std::string information_content = in_value["content"].asString();
            std::cout<<"[修改的语料行为："<<information_id<<"]"<<std::endl;
            std::cout<<"[新语料行修改的内容为："<<information_content<<"]"<<std::endl;

            std::string filename = "../wwwroot/MainPagehtml/datasets.txt";  // 替换为实际的文件名
            int lineId = std::stoi(information_id);  // 要替换的行号，从 1 开始计数
            std::string content = information_content;  // 替换的内容

            return replaceLineInFile(filename, lineId, content);
        }

    public:
        int execute_create(MYSQL *conn, const char *_username, const char *_password)
        {
            char sql[512];
            MYSQL_STMT *stmt;
            MYSQL_BIND bind[2];
            int ret = 0;
                
            if (conn == NULL || _username == NULL || _password == NULL) {
                fprintf(stderr, "Invalid input parameters\n");
                return 0;
            }

            stmt = mysql_stmt_init(conn);
            if (!stmt) {
                fprintf(stderr, "mysql_stmt_init() failed\n");
                return 0;
            }

            const char *query = "INSERT INTO user (username, password) VALUES (?, ?)";
            if (mysql_stmt_prepare(stmt, query, strlen(query))) {
                fprintf(stderr, "mysql_stmt_prepare() failed: %s\n", mysql_stmt_error(stmt));
                mysql_stmt_close(stmt);
                return 0;
            }

            memset(bind, 0, sizeof(bind));

            bind[0].buffer_type = MYSQL_TYPE_STRING;
            bind[0].buffer = (char*)_username;
            bind[0].buffer_length = strlen(_username);

            bind[1].buffer_type = MYSQL_TYPE_STRING;
            bind[1].buffer = (char*)_password;
            bind[1].buffer_length = strlen(_password);

            if (mysql_stmt_bind_param(stmt, bind)) {
                fprintf(stderr, "mysql_stmt_bind_param() failed: %s\n", mysql_stmt_error(stmt));
                mysql_stmt_close(stmt);
                return 0;
            }

            if (mysql_stmt_execute(stmt)) {
                fprintf(stderr, "mysql_stmt_execute() failed: %s\n", mysql_stmt_error(stmt));
                mysql_stmt_close(stmt);
                return 0;
            }

            if (mysql_stmt_affected_rows(stmt) == 1) {
                ret = 1; 
            }

            mysql_stmt_close(stmt);

            return ret;
        }
        int create_sysuser(const std::string in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_username = in_value["username"].asString();
            std::string information_password = in_value["password"].asString();
            std::cout<<"[创建普通用户的用户名为："<<information_username<<"]"<<std::endl;
            std::cout<<"[创建普通用户的密码为："<<information_password<<"]"<<std::endl;

            //初始化 MySQL 连接
            MYSQL *conn = mysql_init(NULL);
            if (conn == NULL)
            {
                fprintf(stderr, "MySQL 初始化失败: %s\n", mysql_error(conn));
                return 0;
            }
            // 连接到 MySQL 数据库
            if (mysql_real_connect(conn, "localhost", "root", "", "as_db", 0, NULL, 0) == NULL)
            {
                fprintf(stderr, "连接数据库失败: %s\n", mysql_error(conn));
                mysql_close(conn);
                return 0;
            }
            // 执行查询并获取结果
            const char *elem_1 = information_username.c_str();
            const char *elem_2 = information_password.c_str();
            int result = execute_create(conn, elem_1, elem_2);
            // 关闭 MySQL 连接
            mysql_close(conn);
            return result;
        }
        
        int execute_delete(MYSQL *conn, const char *_username,  const char *_password){
         MYSQL_STMT *stmt = NULL;
        MYSQL_BIND bind[2];
        int ret = 0;

        if (conn == NULL || _username == NULL || _password == NULL) {
            fprintf(stderr, "Invalid input parameters\n");
            return 0;
        }

        stmt = mysql_stmt_init(conn);
        if (!stmt) {
            fprintf(stderr, "mysql_stmt_init() failed\n");
            return 0;
        }

        const char *query = "DELETE FROM user WHERE username = ? AND password = ?";
        if (mysql_stmt_prepare(stmt, query, strlen(query))) {
            fprintf(stderr, "mysql_stmt_prepare() failed: %s\n", mysql_stmt_error(stmt));
            goto cleanup;
        }

        memset(bind, 0, sizeof(bind));

        bind[0].buffer_type = MYSQL_TYPE_STRING;
        bind[0].buffer = (char*)_username;
        bind[0].buffer_length = strlen(_username);

        bind[1].buffer_type = MYSQL_TYPE_STRING;
        bind[1].buffer = (char*)_password;
        bind[1].buffer_length = strlen(_password);

        if (mysql_stmt_bind_param(stmt, bind)) {
            fprintf(stderr, "mysql_stmt_bind_param() failed: %s\n", mysql_stmt_error(stmt));
            goto cleanup;
        }

        if (mysql_stmt_execute(stmt)) {
            fprintf(stderr, "mysql_stmt_execute() failed: %s\n", mysql_stmt_error(stmt));
            goto cleanup;
        }

        if (mysql_stmt_affected_rows(stmt) > 0) {
            ret=1;
        }else{
                fprintf(stderr, "No records matched the criteria\n");
        }

cleanup:
        if (stmt){
            mysql_stmt_close(stmt);
        }
        return ret;
        
        }
        int delete_sysuser(const std::string in_json)
        {
            Json::Reader reader;
            Json::Value in_value;
            reader.parse(in_json, in_value);
            std::string information_username = in_value["username"].asString();
            std::string information_password = in_value["password"].asString();
            std::cout<<"[删除普通用户的用户名为："<<information_username<<"]"<<std::endl;
            std::cout<<"[删除普通用户的密码为："<<information_password<<"]"<<std::endl;
            
            MYSQL *conn = mysql_init(NULL);
            if (conn == NULL)
            {
                fprintf(stderr, "MySQL 初始化失败: %s\n",mysql_error(conn));
                return 0;
            }

            if (mysql_real_connect(conn, "localhost", "root", "",     "as_db", 0, NULL, 0) == NULL)
            {
                fprintf(stderr, "连接数据库失败: %s\n",mysql_error(conn));
                mysql_close(conn); 
                return 0;
            }

            const char *elem_1 = information_username.c_str();
            const char *elem_2 = information_password.c_str();
            int result = execute_delete(conn, elem_1, elem_2);
                
            mysql_close(conn);     
            return result;
        }
    private:
    };
}
